package model.persistence;
import java.util.HashMap;
import java.util.Map;

public abstract class AbstractDAOFactory implements DAOFactory{

    public static final String SQLITE = "model.persistence.SQLiteDAOFactory"; //nome canonico
    public static final String POSTGRES = "model.persistence.PostgresDAOFactory";
    public static final String MYSQL = "model.persistence.MySQLDAOFactory";

    //Map - possui uma chave e um valor - uma tabela
    private static Map<String, DAOFactory> factories; //tabela - a chave é uma instancia de um banco de dados, acima

    static{
        AbstractDAOFactory.factories = new HashMap<String, DAOFactory>();
    }

    protected AbstractDAOFactory(){//protected - a nivel de hierarquia, para que somente as sub-classes possam enxergar esta superclasse
        
    }

    public static DAOFactory getDAOFactory(String dbType) throws ClassNotFoundException, IllegalAccessException, InstantiationException{
        if(dbType == null || dbType.equals(""))
            throw new IllegalArgumentException("Tipo de banco de dados inválido.");

        DAOFactory factory = null;

        if(! AbstractDAOFactory.factories.containsKey(dbType)){
             try{
                 Class cls = Class.forName(dbType); //import dinamicamente //retorna a classe carregada //só funciona se a classe nao tiver construtor com parametros
                 factory = (DAOFactory) cls.newInstance();
                 AbstractDAOFactory.factories.put(dbType, factory);
             } catch(ClassNotFoundException erro){
                 throw new ClassNotFoundException("Banco de dados não suportado. \n Motivo: \n" + erro.getMessage());
             } catch(IllegalAccessException erro){
                 throw new IllegalAccessException("Não foi possível instanciar o acesso a dados. \n Motivo: \n " + erro.getMessage());
             }catch(InstantiationException erro){
                 throw new InstantiationException("Não foi possível instanciar o acesso a dados. \n Motivo: \n " + erro.getMessage());
             }
        }else{
            factory = AbstractDAOFactory.factories.get(dbType); //se existir no mapa, é atribuido a factory
        }
        return factory;
    }
}
